package com.cli.springboot_rabbitmq.consumer;

import com.cli.springboot_rabbitmq.model.User;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @Author xiongmin
 * @Description
 * @Date 2021/2/26 11:54
 * @Version 1.0
 **/
@Component
@Slf4j
@RabbitListener(queues = "topic.WOMAN") //监听的队列名称 topic.WOMAN
public class TopicConsumerListenerTwo {


//    @RabbitHandler
//    public void receive(@Payload String message, @Headers Map<String, Object> headers) {
//        try {
//            log.info("TopicReceiver消费者收到消息  : ");
//            log.info("message = " + message);
//
//            log.info("TopicReceiver消费者收到消息头部信息  : ");
//            if (null != headers && !headers.isEmpty()) {
//                headers.forEach((key, value) -> {
//                    log.info(key + ": " + value + "\n");
//                });
//            } else {
//                log.info("headers is empty");
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//        }
//    }

    /**
     * 如果生产者生产的消息类型为String,那么就会执行该方法处理消息
     * @param msg
     */
    @RabbitHandler
    public void receive(@Payload String msg, Channel channel, Message message) {
        try {
            try {
                log.info("TopicReceiver消费者收到消息  : ");
                log.info("msg = " + msg);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            // 确认消息被消费
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            try {
                if (message.getMessageProperties().getRedelivered()) {
                    log.error("消息已重复处理失败,拒绝再次接收...");
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
                } else  {
                    log.error("消息即将返回队列再次处理");
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                }
            } catch (Exception ex) {
                log.error("消息消费异常时处理失败",ex.getMessage(),ex);
            }

        }
    }


//    @RabbitHandler
//    public void receive(@Payload User user, @Headers Map<String, Object> headers) {
//        try {
//            log.info("TopicReceiver消费者收到消息  : ");
//            log.info("user = " + user);
//
//            log.info("TopicReceiver消费者收到消息头部信息  : ");
//            if (null != headers && !headers.isEmpty()) {
//                headers.forEach((key, value) -> {
//                    log.info(key + ": " + value + "\n");
//                });
//            } else {
//                log.info("headers is empty");
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage(), e);
//        }
//    }

    /**
     * 如果生产者生产的消息类型为User,那么就会执行该方法处理消息
     * @param user
     */
    @RabbitHandler
    public void receive(@Payload User user, Channel channel, Message message) {
        try {
            try {
                log.info("TopicReceiver消费者收到消息  : ");
                log.info("user = " + user);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            // 确认消息被消费
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            try {
                if (message.getMessageProperties().getRedelivered()) {
                    log.error("消息已重复处理失败,拒绝再次接收...");
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
                } else  {
                    log.error("消息即将返回队列再次处理");
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                }
            } catch (Exception ex) {
                log.error("消息消费异常时处理失败",ex.getMessage(),ex);
            }

        }
    }

    /**
     * 如果生产者生产的消息类型为Map,那么就会执行该方法处理消息
     * @param msg
     */
    @RabbitHandler
    public void receive(@Payload Map msg, Channel channel, Message message) {
        try {
            log.info("TopicReceiver {topic.WOMAN}消费者收到消息  : ");
            if (null != msg && !msg.isEmpty()) {
                msg.forEach((key, value) -> {
                    log.info(key + ": " + value + "\n");
                });
            } else {
                log.info("msg is empty");
            }
            // 确认消息被消费
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            try {
                if (message.getMessageProperties().getRedelivered()) {
                    log.error("消息已重复处理失败,拒绝再次接收...");
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false); // 拒绝消息
                } else  {
                    log.error("消息即将返回队列再次处理");
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                }
            } catch (Exception ex) {
                log.error("消息消费异常时处理失败",ex.getMessage(),ex);
            }

        }
    }


    /**
     * @DO 总结
     * @RabbitListener标注在类上面表示当有收到消息的时候，就交给带有@RabbitHandler的方法处理，具体找哪个方法处理，需要更具MessageConverter转换后的java对象。
     * 注意，如果需要消息的头部信息，由于头部信息是一个MAP数据结构，那么Payload的数据类型不能为MAP类型，否者会报错，且即使其他不是Map类型的Payload，要获取消息的头部信息也会报错
     * 因为消费者消息Payload是MAP的类型的消息时，会查看那个方法中有MAP, 当有多个方法中具有MAP参数时，此时程序也不知道该使用哪个方法来处理这个消息，就会抛出异常
     */

}